home *** CD-ROM | disk | FTP | other *** search
/ Tech Arsenal 1 / Tech Arsenal (Arsenal Computer).ISO / tek-04 / ddj0492.zip / HANDPRIN.ASC < prev    next >
Text File  |  1992-03-10  |  5KB  |  138 lines

  1. _YOUR OWN HANDPRINTING RECOGNITION ENGINE_
  2. by Ron Avitzur
  3.  
  4.  
  5. [LISTING ONE]
  6.  
  7. /*****************************************************************
  8. A Writer-Dependent Hand-printing Recognizer -- by Ron Avitzur, 1991.
  9. This is not the complete code. See the accompanying article for 
  10. a description of other necessary modules.
  11. *****************************************************************/
  12.  
  13. typedef struct { short num_items; void  *items[]; } *List;
  14. typedef struct { short code;  List strokes; } GesturePattern
  15. typedef struct { char is_dot; List s[5];    } StrokePattern;
  16. typedef struct {
  17.         Point    Ink[MAX_POINTS],
  18.                  P[MAX_N];
  19.         short    Ink_Num,
  20.                  N,
  21.                  T[MAX_N],
  22.                  IsDot;
  23.         unsigned long S[5];
  24.         double   Aspect_Ratio;
  25.         long     Xmax,Xmin,
  26.                  Ymax,Ymin,
  27.                  Height,Width,
  28.                  XmaxT,XminT,
  29.                  YmaxT,YminT,
  30.                  HeightT,WidthT;
  31.         long     start_time,end_time;
  32.         List     matches;
  33.         } StrokeData,
  34.          *StrokePtr;
  35.  
  36. ProcPtr HashFunctions[] = { Fxn1,Fxn2,Fxn3,Fxn4,Fxn5 };
  37.  
  38. char Bits[] = {2,2,3,2,2};
  39.  
  40. #define DOT_THRESHHOLD              (Wacom?80:4)
  41. #define PT_SEP_POST                 (Wacom?40:4)
  42.  
  43. /****************************************************************/
  44. void Analyze(register StrokePtr theStroke) {
  45.         char i,s[100];
  46.         Simplify();
  47.         for (i = 0; i < 5; i++) {
  48.                 HashFunction[i](s,theStroke);
  49.  
  50.                 ConvertStringToLong(s,&S[i],Bits[i]);
  51.                 }
  52.         theStroke->IsDot = 
  53.            ((theStroke->Height < DOT_THRESHHOLD  
  54.             &&
  55.             theStroke->Width  < DOT_THRESHHOLD) 
  56.          || N == 1);
  57.         }
  58. /****************************************************************/
  59. void    Simplify(StrokePtr theStroke,Point *Ink,short N) {
  60.         Point Q[MAX_POINTS];
  61.         short min_dx = theStroke->Width  / 8,
  62.               min_dy = theStroke->Height / 8;
  63.         if (theStroke->Aspect_Ratio < 0.2) min_dy = theStroke->Height;
  64.         if (theStroke->Aspect_Ratio > 5.0) min_dx = theStroke->Width;
  65.         theStroke->N = Process3(theStroke->P,Ink,N,min_dx,min_dy);
  66.         ComputeT(theStroke);
  67.         }
  68. /****************************************************************/
  69. void ComputeT(StrokePtr theStroke) {
  70.         register short *T  = theStroke->T;
  71.         register Point *P  = theStroke->P;
  72.         register short i,N = theStroke->N;
  73.         for (i = 0; i < N - 1; i++)
  74.                 T[i] = ATAN2(P[i+1].v-P[i].v,P[i+1].h-P[i].h);
  75.         }
  76. /****************************************************************/
  77. short Process3(register Point *P, register Point *Q,
  78.                short num,short xd, short yd) {
  79.         register short i,n;
  80.         register short dx,dy;
  81.         n = 0;
  82.         P[0] = Q[0];
  83.         for (i = 1; i < num - 1; i++) {
  84.                 dx = Q[i].h - P[n].h; dx = ABS(dx);
  85.                 dy = Q[i].v - P[n].v; dy = ABS(dy);
  86.                 if (dx + dy < PT_SEP_POST)      continue;
  87.                 if (dx < xd && dy < yd)         continue;
  88.                 n++;
  89.                 P[n] = Q[i];
  90.                 }
  91.         dx = Q[num - 1].h - P[n].h;
  92.         dy = Q[num - 1].v - P[n].v;
  93.         if (ABS(dx) + ABS(dy) > PT_SEP_POST)
  94.                 n++;
  95.         P[n] = Q[num - 1];
  96.         return n + 1;
  97.         }
  98. /****************************************************************/
  99. /* These five lines determine what the features actually are. */
  100. #define Feature1(t) ('0' + ((t + 10 + 45 + 180) / 90) % 4)
  101. #define Feature2(t) ('0' + ((t + 10 + 00 + 180) / 90) % 4)
  102.  
  103. #define Feature3(t) ('0' + ((t + 10 + 22 + 180) / 45) % 8)
  104. #define Feature4(p) ('0' + (4*((p).h - theStroke->XminT) /theStroke->WidthT))
  105. #define Feature5(p) ('0' + (4*((p).v - theStroke->YminT) /theStroke->HeightT))
  106.  
  107. /****************************************************************/
  108. #define FOO(name,fxn,type,array,end)           \
  109.         void name(char *s,StrokePtr theStroke) \
  110.         {                                      \
  111.         register short i,d,n = 0;              \
  112.         register type *T = theStroke->array;   \
  113.         s[0] = fxn(*T++);                      \
  114.         i = theStroke->N - end;                \
  115.         while (i-- > 0) {                      \
  116.                 d = fxn(*T++);                 \
  117.                 if (s[n] != d)                 \
  118.                         s[++n] = d;            \
  119.                 }                              \
  120.         s[++n] = 0;                            \
  121.         }
  122. FOO(Fxn1,Feature1,short,T,2)
  123. FOO(Fxn2,Feature2,short,T,2)
  124. FOO(Fxn3,Feature3,short,T,2)
  125. FOO(Fxn4,Feature4,Point,P,1)
  126. FOO(Fxn5,Feature5,Point,P,1)
  127. /****************************************************************/
  128. void ConvertStringToLong(char *s,unsigned long *np,short bits) {
  129.         unsigned long n = 0;
  130.         short i,len = strlen(s);
  131.         s[len] = s[len-1];
  132.         if (len > 32/bits) len = 32/bits;
  133.         for (i = 0; i <= len; i++)
  134.                 n = (n << bits) + s[len - i] - '0';
  135.         *np = n;
  136.         }
  137.  
  138.